import { RigidBody, useRapier } from "@react-three/rapier";
import { useKeyboardControls } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import { useRef } from "react";
import { useEffect } from "react";
import * as THREE from "three";
import useGame from "../../../../stores/useGame.js";
/**
 *
 *  玩家
 */
function Player() {
  const start = useGame((state) => state.start);
  const end = useGame((state) => state.end);
  const reStart = useGame((state) => state.reStart);
  const blockCount = useGame((state) => state.blockCount);
  

  const playerRef = useRef();
  // Exposes the Rapier context, and world
  const { rapier, world } = useRapier();
  // 获取物理世界实例
  const rapierWorld = world;
  const [subKeys, getKeys] = useKeyboardControls();
  const smoothedCameraPosition = new THREE.Vector3(10, 10, 10);
  const smoothedCameraTarget = new THREE.Vector3();
  const reset = () => {
    // 设置位置到初始位置
    // 移除施加在球体上的扭矩和力
    if (playerRef.current) {
      playerRef.current.setTranslation({ x: 0, y: 1, z: 0 });
      playerRef.current.setLinvel({ x: 0, y: 0, z: 0 });
      playerRef.current.setAngvel({ x: 0, y: 0, z: 0 });
    }
  };
  /**
   * 对于跳跃，我们不会在每一帧中监听它，而是使用 useEffect 监听它，
   * 当它发生变化时，再执行跳跃逻辑。订阅跳跃键被按下
   */
  useEffect(() => {
    const unSub = subKeys(
      (state) => state.jump,
      (value) => {
        /**
         * 只有球体碰撞的时间小于0.15，才可以跳跃
         */
        if (playerRef.current && value) {
          const player = playerRef.current;
          const origin = player.translation();
          origin.y -= 0.31;
          const direction = { x: 0, y: -1, z: 0 };
          const ray = new rapier.Ray(origin, direction);
          const hit = rapierWorld.castRay(ray, 10, true);
          if (hit.timeOfImpact < 0.15) {
            player.applyImpulse({ x: 0, y: 0.5, z: 0 });
          }
        }
      }
    );
    // 订阅操作键被按下
    const unSubAnyKeys = subKeys(() => {
      // 当按下操作按钮的时候，游戏开始
      console.log("有按键被按下");
      start();
    });
    // 订阅store中的变化
    const unSubUseGame = useGame.subscribe(
      (state) => state.gameState,
      (value) => {
        console.log("useGame 的store发生了变化", value);
        if (value === "ready") {
          reset();
        }
      }
    );
    return () => {
      // 销毁时取消订阅
      unSub();
      unSubAnyKeys();
      unSubUseGame();
    };
  }, []);
  /**
   * 玩家水平移动控制
   */
  const controlPlay = (delta) => {
    if (playerRef.current) {
      const player = playerRef.current;
      const { forward, right, left, back, jump } = getKeys();
      // console.log(forward, right, left, back, jump);
      /**
       * 根据玩家所按的键来综合处理，计算出最终的冲量和扭矩
       */
      const impulse = { x: 0, y: 0, z: 0 }; // 冲量
      const torque = { x: 0, y: 0, z: 0 }; // 扭矩
      const impulseStrength = 0.6 * delta;
      const torqueStrength = 0.2 * delta;
      if (forward || right || left || back || jump) {
        player.wakeUp();
      }

      if (forward) {
        impulse.z -= impulseStrength;
        torque.x -= torqueStrength;
      }
      if (right) {
        impulse.x += impulseStrength;
        torque.z -= torqueStrength;
      }
      if (left) {
        impulse.x -= impulseStrength;
        torque.z += torqueStrength;
      }
      if (back) {
        impulse.z += impulseStrength;
        torque.x += torqueStrength;
      }
      player.applyImpulse(impulse);
      player.applyTorqueImpulse(torque); //施加扭矩冲量
    }
  };
  /**
   * 相机位置控制
   */
  const controlCamer = (state, delta) => {
    const { camera } = state;
    if (playerRef.current) {
      const playerPosition = playerRef.current.translation();
      const cameraPosition = new THREE.Vector3();
      cameraPosition.copy(playerPosition);
      cameraPosition.z += 2.25;
      cameraPosition.y += 0.65;
      const cameraTarget = new THREE.Vector3();
      cameraTarget.copy(playerPosition);
      cameraTarget.y += 0.25;

      smoothedCameraPosition.lerp(cameraPosition, 5 * delta);
      smoothedCameraTarget.lerp(cameraTarget, 5 * delta);

      camera.position.copy(smoothedCameraPosition);
      camera.lookAt(smoothedCameraTarget);

      if (playerPosition.z < -(blockCount * 4 + 2)) {
        // 当到达终点的时候，设置gameState为“ended”
        end();
      }
      if (playerPosition.y < -3) {
        // 当到达掉落的时候，设置gameState为“ready”
        reStart();
      }
      // console.log('blockCount',blockCount);
    }
  };
  useFrame((state, delta) => {
    controlPlay(delta);
    controlCamer(state, delta);
  });

  return (
    <>
      <RigidBody
        ref={playerRef}
        position={[0, 1.5, 0]}
        colliders="ball"
        restitution={0.2}
        // 设置摩擦力，滚动的时候运动
        friction={1}
        // 为刚体设置阻尼，这样可以减少位移速度
        linearDamping={0.5}
        //为刚体设置角阻尼（angular damping），这样可以减少旋转速度
        angularDamping={0.5}
      >
        <mesh castShadow>
          <icosahedronGeometry args={[0.3, 1]}></icosahedronGeometry>
          <meshStandardMaterial
            flatShading
            color={"mediumpurple"}
          ></meshStandardMaterial>
        </mesh>
      </RigidBody>
    </>
  );
}
export default Player;
